package com.ppt.javappt.entity;

import com.ppt.javappt.HelloApplication;
import com.ppt.javappt.util.FileUtil;
import com.ppt.javappt.util.StringUtil;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.paint.Color;
import javafx.embed.swing.SwingFXUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * @author cys
 * 单页幻灯片
 */
public class Slide extends AnchorPane implements Serializable {
    // 快照的缓存
    private final ObjectProperty<WritableImage> thumbnail = new SimpleObjectProperty<>();
    // 提供获取属性本身的方法（用于监听或绑定）
    public ObjectProperty<WritableImage> thumbnailProperty() {
        return thumbnail;
    }
    // 提供设置值的方法（会自动通知监听器）
    public void setThumbnail(WritableImage image) {
        // 调用 set 方法触发通知
        this.thumbnail.set(image);
    }
    // 提供获取当前值的方法
    public WritableImage getThumbnail() {
        return thumbnail.get();
    }
    //    private WritableImage thumbnailCache;
    //    有待考证
    private List<Node> nodeList;

    // 1. 定义通用的属性变化处理器（触发缩略图更新）
    private final ChangeListener<Object> propertyChangeListener = (obs, oldVal, newVal) -> {
        updateThumbnail();
    };

    // 2. 初始化管理器（自动管理所有处理器）
    private final NodeListenerManager listenerManager = new NodeListenerManager();

    public Slide(){
        this.setBackground(Background.fill(Color.WHITE));
        nodeList = new ArrayList<>();
        this.setPrefSize(800, 600);
        // TODO 属性变化时也要监听
//        this.getChildren().addListener((ListChangeListener<Node>) change ->{
//            updateThumbnail();
//        });
        // 监听子节点列表变化
        this.getChildren().addListener((ListChangeListener<Node>) change -> {
            while (change.next()) {
                // 处理新增节点：通过管理器添加所有适用的监听器
                if (change.wasAdded()) {
                    for (Node node : change.getAddedSubList()) {
                        listenerManager.addListeners(node, propertyChangeListener);
                    }
                }
                // 处理移除节点：通过管理器移除所有监听器（避免内存泄漏）
                if (change.wasRemoved()) {
                    for (Node node : change.getRemoved()) {
                        listenerManager.removeListeners(node, propertyChangeListener);
                    }
                }
            }
            updateThumbnail();
        });

        // 为初始已存在的子节点添加监听器
        for (Node node : this.getChildren()) {
            listenerManager.addListeners(node, propertyChangeListener);
        }
        updateThumbnail();
        this.setVisible(true);
    }

    // 当幻灯片内容修改时，调用此方法更新缓存
    public void updateThumbnail() {
        SnapshotParameters params = new SnapshotParameters();
        params.setFill(javafx.scene.paint.Color.WHITE);
        // 直接生成缩略图尺寸的快照
        setThumbnail((this.snapshot(params,new WritableImage(800,600))));
    }

    // 导出为图片
    public void outputAsImage(){
        String[] formats = ImageIO.getWriterFormatNames();
        System.out.println("支持的格式：" + Arrays.toString(formats));

        File file = FileUtil.saveImage(HelloApplication.MainWindow);
        if(file!=null){
            try {
                // 获取文件名（含后缀）
                String fileName = file.getName();
                String extension = StringUtil.getFileExtension(fileName);
                System.out.println(extension);
                BufferedImage bufferedImage = SwingFXUtils.fromFXImage(thumbnail.get(), null);

                if("png".equals(extension)){
                    ImageIO.write(bufferedImage,"png", file);
                }else if("jpg".equals(extension)){
                    BufferedImage jpgImage = new BufferedImage(800,600,BufferedImage.TYPE_INT_RGB);
                    jpgImage.getGraphics().drawImage(bufferedImage,0,0,null);
                    ImageIO.write(jpgImage,"jpg",file);
                }

            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
